package ift605.EquationWithTrainingAgents.behavior.special.complex;

import jade.core.AID;
import jade.lang.acl.ACLMessage;

import java.util.List;

import javax.naming.directory.InvalidAttributesException;

import ift605.EquationWithTrainingAgents.behavior.common.DeriverBehavior;
import ift605.EquationWithTrainingAgents.struct.DerivationInfo;
import ift605.EquationWithTrainingAgents.struct.DerivationStep;
import ift605.EquationWithTrainingAgents.struct.LearningMessage;
import udes.ds.agent.AbstractEquation;
import udes.ds.agent.MultiplicativeEquation;
import udes.ds.agent.SummativeEquation;

public class MultNumericPartEquationBehavior extends DeriverBehavior {
	private static final long serialVersionUID = 1L;

	@Override
	public boolean derive(List<DerivationInfo> aDerivationInfos) {
		DerivationInfo current = aDerivationInfos.get(0);
		
		AbstractEquation base = current.Mess.base;
		AbstractEquation currentDerivation = current.Mess.derived;
		
		Object[] baseValues = base.getValues();
		Object[] currentDerivationValues = currentDerivation.getValues();
		
		if(current.Mess.tryDerive)
		{
			aDerivationInfos.clear();
			
			for(int i =0; i < baseValues.length; ++i)
			{
				for(int j =0; j < currentDerivationValues.length; ++j)
				{
					Integer[] variation = new Integer[]{i,j};
					DerivationInfo newInfo = new DerivationInfo((LearningMessage)Clone(current.Mess), variation);
					
					boolean firstArgumentIsNumeric =  Double.class.isAssignableFrom(currentDerivationValues[j].getClass()) || Integer.class.isAssignableFrom(currentDerivationValues[j].getClass());
					boolean SecondArgumentIsNumeric =  Double.class.isAssignableFrom(baseValues[i].getClass()) || Integer.class.isAssignableFrom(baseValues[i].getClass());
					
					if(firstArgumentIsNumeric && SecondArgumentIsNumeric)
					{	
						AbstractEquation newDerivation = (AbstractEquation)Clone(newInfo.Mess.derived);
						Object[] newValues = newDerivation.getValues() ;
						
						if(newValues[j] instanceof Double)
						{
							if(baseValues[i] instanceof Integer)
							{		
								newValues[j] =(Double)((Double)newValues[j] * (Integer)baseValues[i]) ;
							}
							else //There we suppose a Double
							{
								newValues[j] =(Double)((Double)newValues[j] * (Double)baseValues[i]) ;
							}
						}
						else //There we suppose an INT
						{
							if(baseValues[i] instanceof Integer)
							{
								newValues[j] =(Integer)((Integer)newValues[j] * (Integer)baseValues[i]) ;
							}
							else //There we suppose a Double
							{
								newValues[j] =(int)((Integer)newValues[j] * (Double)baseValues[i]) ;
							}
						}
						
						try {
							newDerivation.setValues(newValues);
							
							newInfo.Mess.derived = newDerivation;
							
							aDerivationInfos.add(newInfo);
						
						} catch (InvalidAttributesException e) {
							e.printStackTrace();
						}
					}
					
				/*
					System.out.println(">> MULT :: FROM");
					base.printUserReadable();
					currentDerivation.printUserReadable();
					System.out.println(">> TO -- " + i + " " + j);
					newInfo.Mess.base.printUserReadable();
					newInfo.Mess.derived.printUserReadable();
					System.out.println("<<<<<<<<<<<<<<<<");*/
				}
			}
		}
		else
		{
			Integer[] variation = (Integer[]) current.Variation;

			current.Mess.derived = (AbstractEquation) Clone(current.Mess.derived);
			Object[] newValues = current.Mess.derived.getValues();
			
			if(newValues[variation[1]] instanceof Double)
			{
				if(baseValues[variation[0]] instanceof Integer)
				{		
					newValues[variation[1]] =(Double)((Double)newValues[variation[1]] * (Integer)baseValues[variation[0]]) ;
				}
				else //There we suppose a Double
				{
					newValues[variation[1]] =(Double)((Double)newValues[variation[1]] * (Double)baseValues[variation[0]]) ;
				}
			}
			else //There we suppose an INT
			{
				if(baseValues[variation[0]] instanceof Integer)
				{
					newValues[variation[1]] =(Integer)((Integer)newValues[variation[1]] * (Integer)baseValues[variation[0]]) ;
				}
				else //There we suppose a Double
				{
					newValues[variation[1]] =(int)((Integer)newValues[variation[1]] * (Double)baseValues[variation[0]]) ;
				}
			}

			try
			{
				current.Mess.derived.setValues(newValues);
			} 
			catch (InvalidAttributesException e) {
				e.printStackTrace();
			} 
		}
		return true;
	}
}